if(!require("plotly")) {install.packages("plotly")}
# install.packages("latex2exp")
# install.packages("BiocManager")
# install.packages("corrplot")
# BiocManager::install("EBImage")
if(!require("lme4")){install.packages("lme4")}
if(!require("lmerTest")){install.packages("lmerTest")}
if(!require("nlme")){install.packages("nlme")}
if(!require("formattable")){install.packages("formattable")}
if(!require("xgboost")){install.packages("xgboost")}
if(!require("processx")) {install.packages("processx")}
library(plotly)
library(lme4)
library(lmerTest)
library(nlme)
library(formattable)
library(xgboost)
### Load libraries
library(EBImage)
library(ggplot2)
library(stringr)
library(gridExtra)
library(latex2exp)
packageVersion('plotly')
[1] ‘4.9.1’
Sys.setenv("plotly_username"="thuynh32")
Sys.setenv("plotly_api_key"="xcSv1yzujDc1IGEwQlr2")
colorBlue = "#007fff"
colorRed = "#ff7f7f"
colorGray = "#cccccc"
colorGreen = "#11ff00"
all_Drive1 <- read.csv('../../../data/TT1/preprocessed/All/TT1_Drive_1_30m_30m.csv')
all_Drive1$Subject <- as.factor(all_Drive1$Subject)
all_Drive1$logPerspiration <- log(all_Drive1$Perspiration)
persons = c("01", "02", "03", "04", "05", "06", "07",
"09", "12", "13", "15", "16", "17", "18",
"22", "24", "29", "30", "31", "32", "41")
mean_pp <- vector(mode="list", length=length(persons))
names(mean_pp) <- persons
std_pp <- vector(mode="list", length=length(persons))
names(std_pp) <- persons
# Segments
mean_pp_seg0 <- vector(mode="list", length=length(persons))
names(mean_pp_seg0) <- persons
mean_pp_seg1 <- vector(mode="list", length=length(persons))
names(mean_pp_seg1) <- persons
mean_pp_seg2 <- vector(mode="list", length=length(persons))
names(mean_pp_seg2) <- persons
mean_pp_seg3 <- vector(mode="list", length=length(persons))
names(mean_pp_seg3) <- persons
mean_pp_seg4 <- vector(mode="list", length=length(persons))
names(mean_pp_seg4) <- persons
for(p in persons) {
pData <- all_Drive1[(all_Drive1$Subject==as.integer(p) | all_Drive1$Subject==p),]
pData_act1 <- pData[pData$Activity == 1,]
if(p == "41") {
# This subjest has suspecious PP in the last phase (Phase = 4)
pData_seg0 <- pData[pData$Phase==0 & pData$Time <= 370,]
} else {
pData_seg0 <- pData[pData$Phase==0,]
}
pData_seg1 <- pData[pData$Phase==1 & pData$Activity==1 & pData$Time < 110,]
pData_seg2 <- pData[pData$Phase==2 & pData$Activity==1 & pData$Time < 250,]
pData_seg3 <- pData[pData$Phase==3 & pData$Activity==1 & pData$Time < 350,]
pData_seg4 <- pData[pData$Phase==4 & pData$Activity==1,]
if(p == "41") {
# This subjest has suspecious PP in the last phase (Phase = 4)
mean_pp[[p]] <- mean(pData_act1[pData_act1$Time <= 370,]$ppLogNormalized)
} else {
mean_pp[[p]] <- mean(pData_act1$ppLogNormalized)
}
std_pp[[p]] <- sd(pData$ppLogNormalized)
mean_pp_seg0[[p]] <- mean(pData_seg0$ppLogNormalized)
mean_pp_seg1[[p]] <- mean(pData_seg1$ppLogNormalized)
mean_pp_seg2[[p]] <- mean(pData_seg2$ppLogNormalized)
mean_pp_seg3[[p]] <- mean(pData_seg3$ppLogNormalized)
if (p == "41") {
mean_pp_seg4[[p]] <- mean_pp[[p]]
} else {
mean_pp_seg4[[p]] <- mean(pData_seg4$ppLogNormalized)
}
}
plt_AllAcc <- vector(mode="list", length=length(persons))
names(plt_AllAcc) <- persons
COLOR_ACC = "#02A3C8"
COLOR_PP = "#F28E8E"
COLOR_BRAKE = "#888888"
y1 <- list(
tickfont = list(color = COLOR_ACC),
title="Degree",
range=c(0, max(all_Drive1$Acceleration))
)
y2 <- list(
tickfont = list(color = COLOR_PP),
overlaying = "y",
side = "right",
title = "Log Perspiration",
showgrid = FALSE,
range=c(min(all_Drive1$ppLogNormalized), max(all_Drive1$ppLogNormalized))
)
for (p in persons) {
pData <- all_Drive1[all_Drive1$Subject==as.integer(p) | all_Drive1$Subject==p,]
pData_seg0 <- pData[pData$Phase==0,]
pData_seg1 <- pData[pData$Phase==1 & pData$Activity==1 & pData$Time < 110,]
pData_seg2 <- pData[pData$Phase==2 & pData$Activity==1 & pData$Time < 250,]
pData_seg3 <- pData[pData$Phase==3 & pData$Activity==1 & pData$Time < 350,]
pData_seg4 <- pData[pData$Phase==4 & pData$Activity==1,]
plot_Acc <- plot_ly(pData, x = ~Time, height=400, width=900) %>%
# add_trace(name="Acceleration", y = ~Acceleration, type = 'scatter', mode = 'lines', line=list(width=1.5, color=COLOR_ACC)) %>%
add_trace(name="PP", y = ~ppLogNormalized, type = 'scatter', mode = 'lines', connectgaps=F, line=list(width=1.5, color=COLOR_PP), yaxis = "y2") %>%
add_segments(x = min(pData$Time), xend = max(pData$Time), y = mean_pp[[p]], yend = mean_pp[[p]],
yaxis = "y2", name="Avg. PP (straight)",
line=list(color="darkgray", dash = 'dot')) %>%
add_segments(x = min(pData$Time), xend = max(pData$Time), y = mean_pp_seg0[[p]], yend = mean_pp_seg0[[p]],
yaxis = "y2", name="Avg. PP (turning)",
line=list(color="black", dash = 'dot')) %>%
add_segments(x = min(pData_seg1$Time), xend = max(pData_seg1$Time), y = mean_pp_seg1[[p]], yend = mean_pp_seg1[[p]],
yaxis = "y2", name="Avg. PP (1st part)",
line=list(color="red", dash = 'dot')) %>%
add_segments(x = min(pData_seg2$Time), xend = max(pData_seg2$Time), y = mean_pp_seg2[[p]], yend = mean_pp_seg2[[p]],
yaxis = "y2", name="Avg. PP (2nd part)",
line=list(color="green", dash = 'dot')) %>%
add_segments(x = min(pData_seg3$Time), xend = max(pData_seg3$Time), y = mean_pp_seg3[[p]], yend = mean_pp_seg3[[p]],
yaxis = "y2", name="Avg. PP (3rd part)",
line=list(color="blue", dash = 'dot')) %>%
add_segments(x = min(pData_seg4$Time), xend = max(pData_seg4$Time), y = mean_pp_seg4[[p]], yend = mean_pp_seg4[[p]],
yaxis = "y2", name="Avg. PP (4th part)",
line=list(color="purple", dash = 'dot')) %>%
layout(
title=paste0("Subject #", p),
xaxis=list(title="Time [s]", range=c(0)),
yaxis=y1,
yaxis2=y2,
margin = list(l = 50, r = 50, b = 50, t = 50, pad = 4),
legend = list(x = 0.5, xanchor = "center", y = 0.2, bgcolor = "rgba(0,0,0,0)", title="Metric", orientation = "h"),
autosize = F
)
plt_AllAcc[[p]] <- plot_Acc
}
htmltools::tagList(plt_AllAcc)
library(dendextend)
NUMBER_OF_CLUSTERS = 4
color_darkpink = "#e75480"
CLUSTER_BRANCH_COLORS <- c("blue", "darkred", color_darkpink, "black")[1:NUMBER_OF_CLUSTERS]
CLUSTER_LABEL_COLORS <- c("blue", "darkred", color_darkpink, "black")[1:NUMBER_OF_CLUSTERS]
dfPP <- as.data.frame(cbind(
unlist(mean_pp),
unlist(std_pp),
unlist(mean_pp_seg0),
unlist(mean_pp_seg1),
unlist(mean_pp_seg2),
unlist(mean_pp_seg3),
unlist(mean_pp_seg4)))
names(dfPP) <- c("MeanPP", "StdPP", "MeanPP_Seg0", "MeanPP_Seg1", "MeanPP_Seg2", "MeanPP_Seg3", "MeanPP_Seg4")
behavioralMatrixClustering <- as.matrix(dfPP)
distMatrix <- dist(behavioralMatrixClustering)
hresults <- distMatrix %>% hclust
hc <- hresults %>%
as.dendrogram %>%
set("nodes_cex", NUMBER_OF_CLUSTERS) %>%
set("labels_col", value = CLUSTER_LABEL_COLORS, k=NUMBER_OF_CLUSTERS) %>%
# set("leaves_pch", 19) %>%
# set("leaves_col", value = c("gray"), k=NUMBER_OF_CLUSTERS) %>%
set("branches_k_color", value=CLUSTER_BRANCH_COLORS, k=NUMBER_OF_CLUSTERS)
plot(hc)
legend("topright",
title="Drive=Cognitive \nHierachical Clustering",
legend = c("Exceptional Increase of PP" , "Slightly Increase of PP" , "No-change or Decrease of PP"),
col = c("darkred", "pink" , "blue"),
pch = c(20,20,20), bty = "n", pt.cex = 1.5, cex = 0.8 ,
text.col = "black", horiz = FALSE, inset = c(0.4, 0.1))

# Store clustering data
fPath <- str_interp("../../../data/TT1/preprocessed/Analysis/TT1_Drive_1_PP.csv")
dfx <- dfPP
dfx <- cbind(persons, dfx)
names(dfx) <- c("Subject", names(dfPP))
write.csv(dfx, fPath, row.names = F)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmlmKCFyZXF1aXJlKCJwbG90bHkiKSkge2luc3RhbGwucGFja2FnZXMoInBsb3RseSIpfQoKIyBpbnN0YWxsLnBhY2thZ2VzKCJsYXRleDJleHAiKQojIGluc3RhbGwucGFja2FnZXMoIkJpb2NNYW5hZ2VyIikgCiMgaW5zdGFsbC5wYWNrYWdlcygiY29ycnBsb3QiKQojIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJFQkltYWdlIikKCmlmKCFyZXF1aXJlKCJsbWU0Iikpe2luc3RhbGwucGFja2FnZXMoImxtZTQiKX0KaWYoIXJlcXVpcmUoImxtZXJUZXN0Iikpe2luc3RhbGwucGFja2FnZXMoImxtZXJUZXN0Iil9CmlmKCFyZXF1aXJlKCJubG1lIikpe2luc3RhbGwucGFja2FnZXMoIm5sbWUiKX0KaWYoIXJlcXVpcmUoImZvcm1hdHRhYmxlIikpe2luc3RhbGwucGFja2FnZXMoImZvcm1hdHRhYmxlIil9CmlmKCFyZXF1aXJlKCJ4Z2Jvb3N0Iikpe2luc3RhbGwucGFja2FnZXMoInhnYm9vc3QiKX0KaWYoIXJlcXVpcmUoInByb2Nlc3N4IikpIHtpbnN0YWxsLnBhY2thZ2VzKCJwcm9jZXNzeCIpfQoKbGlicmFyeShwbG90bHkpCmxpYnJhcnkobG1lNCkKbGlicmFyeShsbWVyVGVzdCkKbGlicmFyeShubG1lKQpsaWJyYXJ5KGZvcm1hdHRhYmxlKQpsaWJyYXJ5KHhnYm9vc3QpCgojIyMgTG9hZCBsaWJyYXJpZXMKbGlicmFyeShFQkltYWdlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkobGF0ZXgyZXhwKQpwYWNrYWdlVmVyc2lvbigncGxvdGx5JykKU3lzLnNldGVudigicGxvdGx5X3VzZXJuYW1lIj0idGh1eW5oMzIiKQpTeXMuc2V0ZW52KCJwbG90bHlfYXBpX2tleSI9InhjU3YxeXp1akRjMUlHRXdRbHIyIikKCmBgYAoKYGBge3J9CmNvbG9yQmx1ZSA9ICIjMDA3ZmZmIgpjb2xvclJlZCA9ICIjZmY3ZjdmIgpjb2xvckdyYXkgPSAiI2NjY2NjYyIKY29sb3JHcmVlbiA9ICIjMTFmZjAwIgoKYWxsX0RyaXZlMSA8LSByZWFkLmNzdignLi4vLi4vLi4vZGF0YS9UVDEvcHJlcHJvY2Vzc2VkL0FsbC9UVDFfRHJpdmVfMV8zMG1fMzBtLmNzdicpCmFsbF9Ecml2ZTEkU3ViamVjdCA8LSBhcy5mYWN0b3IoYWxsX0RyaXZlMSRTdWJqZWN0KQphbGxfRHJpdmUxJGxvZ1BlcnNwaXJhdGlvbiA8LSBsb2coYWxsX0RyaXZlMSRQZXJzcGlyYXRpb24pCgoKcGVyc29ucyAgICAgICAgID0gYygiMDEiLCAgIjAyIiwgIjAzIiwgIjA0IiwgIjA1IiwgICIwNiIsICAiMDciLCAKICAgICAgICAgICAgICAgICAgICAiMDkiLCAgIjEyIiwgIjEzIiwgIjE1IiwgIjE2IiwgICIxNyIsICAiMTgiLCAKICAgICAgICAgICAgICAgICAgICAiMjIiLCAgIjI0IiwgIjI5IiwgIjMwIiwgIjMxIiwgICIzMiIsICAiNDEiKQpgYGAKCgpgYGB7cn0KbWVhbl9wcCA8LSB2ZWN0b3IobW9kZT0ibGlzdCIsIGxlbmd0aD1sZW5ndGgocGVyc29ucykpIApuYW1lcyhtZWFuX3BwKSA8LSBwZXJzb25zCgpzdGRfcHAgPC0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGg9bGVuZ3RoKHBlcnNvbnMpKSAKbmFtZXMoc3RkX3BwKSA8LSBwZXJzb25zCgojIFNlZ21lbnRzCm1lYW5fcHBfc2VnMCA8LSB2ZWN0b3IobW9kZT0ibGlzdCIsIGxlbmd0aD1sZW5ndGgocGVyc29ucykpIApuYW1lcyhtZWFuX3BwX3NlZzApIDwtIHBlcnNvbnMKbWVhbl9wcF9zZWcxIDwtIHZlY3Rvcihtb2RlPSJsaXN0IiwgbGVuZ3RoPWxlbmd0aChwZXJzb25zKSkgCm5hbWVzKG1lYW5fcHBfc2VnMSkgPC0gcGVyc29ucwptZWFuX3BwX3NlZzIgPC0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGg9bGVuZ3RoKHBlcnNvbnMpKSAKbmFtZXMobWVhbl9wcF9zZWcyKSA8LSBwZXJzb25zCm1lYW5fcHBfc2VnMyA8LSB2ZWN0b3IobW9kZT0ibGlzdCIsIGxlbmd0aD1sZW5ndGgocGVyc29ucykpIApuYW1lcyhtZWFuX3BwX3NlZzMpIDwtIHBlcnNvbnMKbWVhbl9wcF9zZWc0IDwtIHZlY3Rvcihtb2RlPSJsaXN0IiwgbGVuZ3RoPWxlbmd0aChwZXJzb25zKSkgCm5hbWVzKG1lYW5fcHBfc2VnNCkgPC0gcGVyc29ucwoKCmZvcihwIGluIHBlcnNvbnMpIHsKICBwRGF0YSA8LSBhbGxfRHJpdmUxWyhhbGxfRHJpdmUxJFN1YmplY3Q9PWFzLmludGVnZXIocCkgfCBhbGxfRHJpdmUxJFN1YmplY3Q9PXApLF0KICBwRGF0YV9hY3QxIDwtIHBEYXRhW3BEYXRhJEFjdGl2aXR5ID09IDEsXQogIAogIGlmKHAgPT0gIjQxIikgewogICAgIyBUaGlzIHN1Ymplc3QgaGFzIHN1c3BlY2lvdXMgUFAgaW4gdGhlIGxhc3QgcGhhc2UgKFBoYXNlID0gNCkKICAgIHBEYXRhX3NlZzAgPC0gcERhdGFbcERhdGEkUGhhc2U9PTAgJiBwRGF0YSRUaW1lIDw9IDM3MCxdCiAgfSBlbHNlIHsKICAgIHBEYXRhX3NlZzAgPC0gcERhdGFbcERhdGEkUGhhc2U9PTAsXQogIH0KICAKICBwRGF0YV9zZWcxIDwtIHBEYXRhW3BEYXRhJFBoYXNlPT0xICYgcERhdGEkQWN0aXZpdHk9PTEgJiBwRGF0YSRUaW1lIDwgMTEwLF0KICBwRGF0YV9zZWcyIDwtIHBEYXRhW3BEYXRhJFBoYXNlPT0yICYgcERhdGEkQWN0aXZpdHk9PTEgJiBwRGF0YSRUaW1lIDwgMjUwLF0KICBwRGF0YV9zZWczIDwtIHBEYXRhW3BEYXRhJFBoYXNlPT0zICYgcERhdGEkQWN0aXZpdHk9PTEgJiBwRGF0YSRUaW1lIDwgMzUwLF0KICBwRGF0YV9zZWc0IDwtIHBEYXRhW3BEYXRhJFBoYXNlPT00ICYgcERhdGEkQWN0aXZpdHk9PTEsXQogIAogIGlmKHAgPT0gIjQxIikgewogICAgIyBUaGlzIHN1Ymplc3QgaGFzIHN1c3BlY2lvdXMgUFAgaW4gdGhlIGxhc3QgcGhhc2UgKFBoYXNlID0gNCkKICAgIG1lYW5fcHBbW3BdXSA8LSBtZWFuKHBEYXRhX2FjdDFbcERhdGFfYWN0MSRUaW1lIDw9IDM3MCxdJHBwTG9nTm9ybWFsaXplZCkKICB9IGVsc2UgewogICAgbWVhbl9wcFtbcF1dIDwtIG1lYW4ocERhdGFfYWN0MSRwcExvZ05vcm1hbGl6ZWQpCiAgfQogIAogIHN0ZF9wcFtbcF1dIDwtIHNkKHBEYXRhJHBwTG9nTm9ybWFsaXplZCkKICBtZWFuX3BwX3NlZzBbW3BdXSA8LSBtZWFuKHBEYXRhX3NlZzAkcHBMb2dOb3JtYWxpemVkKQogIG1lYW5fcHBfc2VnMVtbcF1dIDwtIG1lYW4ocERhdGFfc2VnMSRwcExvZ05vcm1hbGl6ZWQpCiAgbWVhbl9wcF9zZWcyW1twXV0gPC0gbWVhbihwRGF0YV9zZWcyJHBwTG9nTm9ybWFsaXplZCkKICBtZWFuX3BwX3NlZzNbW3BdXSA8LSBtZWFuKHBEYXRhX3NlZzMkcHBMb2dOb3JtYWxpemVkKQogIAogIGlmIChwID09ICI0MSIpIHsKICAgIG1lYW5fcHBfc2VnNFtbcF1dIDwtIG1lYW5fcHBbW3BdXQogIH0gZWxzZSB7CiAgICBtZWFuX3BwX3NlZzRbW3BdXSA8LSBtZWFuKHBEYXRhX3NlZzQkcHBMb2dOb3JtYWxpemVkKQogIH0KfQoKYGBgCgpgYGB7cn0KcGx0X0FsbEFjYyA8LSB2ZWN0b3IobW9kZT0ibGlzdCIsIGxlbmd0aD1sZW5ndGgocGVyc29ucykpIApuYW1lcyhwbHRfQWxsQWNjKSA8LSBwZXJzb25zCgpDT0xPUl9BQ0MgPSAiIzAyQTNDOCIKQ09MT1JfUFAgPSAiI0YyOEU4RSIKQ09MT1JfQlJBS0UgPSAiIzg4ODg4OCIKCnkxIDwtIGxpc3QoCiAgdGlja2ZvbnQgPSBsaXN0KGNvbG9yID0gQ09MT1JfQUNDKSwKICB0aXRsZT0iRGVncmVlIiwKICByYW5nZT1jKDAsIG1heChhbGxfRHJpdmUxJEFjY2VsZXJhdGlvbikpCikKeTIgPC0gbGlzdCgKICB0aWNrZm9udCA9IGxpc3QoY29sb3IgPSBDT0xPUl9QUCksCiAgb3ZlcmxheWluZyA9ICJ5IiwKICBzaWRlID0gInJpZ2h0IiwKICB0aXRsZSA9ICJMb2cgUGVyc3BpcmF0aW9uIiwKICBzaG93Z3JpZCA9IEZBTFNFLAogIHJhbmdlPWMobWluKGFsbF9Ecml2ZTEkcHBMb2dOb3JtYWxpemVkKSwgbWF4KGFsbF9Ecml2ZTEkcHBMb2dOb3JtYWxpemVkKSkKKQoKZm9yIChwIGluIHBlcnNvbnMpIHsKICBwRGF0YSA8LSBhbGxfRHJpdmUxW2FsbF9Ecml2ZTEkU3ViamVjdD09YXMuaW50ZWdlcihwKSB8IGFsbF9Ecml2ZTEkU3ViamVjdD09cCxdCiAgCiAgcERhdGFfc2VnMCA8LSBwRGF0YVtwRGF0YSRQaGFzZT09MCxdCiAgcERhdGFfc2VnMSA8LSBwRGF0YVtwRGF0YSRQaGFzZT09MSAmIHBEYXRhJEFjdGl2aXR5PT0xICYgcERhdGEkVGltZSA8IDExMCxdCiAgcERhdGFfc2VnMiA8LSBwRGF0YVtwRGF0YSRQaGFzZT09MiAmIHBEYXRhJEFjdGl2aXR5PT0xICYgcERhdGEkVGltZSA8IDI1MCxdCiAgcERhdGFfc2VnMyA8LSBwRGF0YVtwRGF0YSRQaGFzZT09MyAmIHBEYXRhJEFjdGl2aXR5PT0xICYgcERhdGEkVGltZSA8IDM1MCxdCiAgcERhdGFfc2VnNCA8LSBwRGF0YVtwRGF0YSRQaGFzZT09NCAmIHBEYXRhJEFjdGl2aXR5PT0xLF0KICAKICBwbG90X0FjYyA8LSBwbG90X2x5KHBEYXRhLCB4ID0gflRpbWUsIGhlaWdodD00MDAsIHdpZHRoPTkwMCkgJT4lCiAgICAjIGFkZF90cmFjZShuYW1lPSJBY2NlbGVyYXRpb24iLCB5ID0gfkFjY2VsZXJhdGlvbiwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcycsIGxpbmU9bGlzdCh3aWR0aD0xLjUsIGNvbG9yPUNPTE9SX0FDQykpICU+JSAKICAgIGFkZF90cmFjZShuYW1lPSJQUCIsIHkgPSB+cHBMb2dOb3JtYWxpemVkLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ2xpbmVzJywgY29ubmVjdGdhcHM9RiwgbGluZT1saXN0KHdpZHRoPTEuNSwgY29sb3I9Q09MT1JfUFApLCB5YXhpcyA9ICJ5MiIpICU+JQogICAgYWRkX3NlZ21lbnRzKHggPSBtaW4ocERhdGEkVGltZSksIHhlbmQgPSBtYXgocERhdGEkVGltZSksIHkgPSBtZWFuX3BwW1twXV0sIHllbmQgPSBtZWFuX3BwW1twXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHlheGlzID0gInkyIiwgbmFtZT0iQXZnLiBQUCAoc3RyYWlnaHQpIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZT1saXN0KGNvbG9yPSJkYXJrZ3JheSIsIGRhc2ggPSAnZG90JykpICU+JQogICAgYWRkX3NlZ21lbnRzKHggPSBtaW4ocERhdGEkVGltZSksIHhlbmQgPSBtYXgocERhdGEkVGltZSksIHkgPSBtZWFuX3BwX3NlZzBbW3BdXSwgeWVuZCA9IG1lYW5fcHBfc2VnMFtbcF1dLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgeWF4aXMgPSAieTIiLCBuYW1lPSJBdmcuIFBQICh0dXJuaW5nKSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iYmxhY2siLCBkYXNoID0gJ2RvdCcpKSAlPiUKICAgIGFkZF9zZWdtZW50cyh4ID0gbWluKHBEYXRhX3NlZzEkVGltZSksIHhlbmQgPSBtYXgocERhdGFfc2VnMSRUaW1lKSwgeSA9IG1lYW5fcHBfc2VnMVtbcF1dLCB5ZW5kID0gbWVhbl9wcF9zZWcxW1twXV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICB5YXhpcyA9ICJ5MiIsIG5hbWU9IkF2Zy4gUFAgKDFzdCBwYXJ0KSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgZGFzaCA9ICdkb3QnKSkgJT4lCiAgICBhZGRfc2VnbWVudHMoeCA9IG1pbihwRGF0YV9zZWcyJFRpbWUpLCB4ZW5kID0gbWF4KHBEYXRhX3NlZzIkVGltZSksIHkgPSBtZWFuX3BwX3NlZzJbW3BdXSwgeWVuZCA9IG1lYW5fcHBfc2VnMltbcF1dLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgeWF4aXMgPSAieTIiLCBuYW1lPSJBdmcuIFBQICgybmQgcGFydCkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWxpc3QoY29sb3I9ImdyZWVuIiwgZGFzaCA9ICdkb3QnKSkgJT4lCiAgICBhZGRfc2VnbWVudHMoeCA9IG1pbihwRGF0YV9zZWczJFRpbWUpLCB4ZW5kID0gbWF4KHBEYXRhX3NlZzMkVGltZSksIHkgPSBtZWFuX3BwX3NlZzNbW3BdXSwgeWVuZCA9IG1lYW5fcHBfc2VnM1tbcF1dLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgeWF4aXMgPSAieTIiLCBuYW1lPSJBdmcuIFBQICgzcmQgcGFydCkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoID0gJ2RvdCcpKSAlPiUKICAgIGFkZF9zZWdtZW50cyh4ID0gbWluKHBEYXRhX3NlZzQkVGltZSksIHhlbmQgPSBtYXgocERhdGFfc2VnNCRUaW1lKSwgeSA9IG1lYW5fcHBfc2VnNFtbcF1dLCB5ZW5kID0gbWVhbl9wcF9zZWc0W1twXV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICB5YXhpcyA9ICJ5MiIsIG5hbWU9IkF2Zy4gUFAgKDR0aCBwYXJ0KSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0icHVycGxlIiwgZGFzaCA9ICdkb3QnKSkgJT4lCiAgICBsYXlvdXQoCiAgICAgIHRpdGxlPXBhc3RlMCgiU3ViamVjdCAjIiwgcCksIAogICAgICB4YXhpcz1saXN0KHRpdGxlPSJUaW1lIFtzXSIsIHJhbmdlPWMoMCkpLCAKICAgICAgeWF4aXM9eTEsIAogICAgICB5YXhpczI9eTIsIAogICAgICBtYXJnaW4gPSBsaXN0KGwgPSA1MCwgciA9IDUwLCBiID0gNTAsIHQgPSA1MCwgcGFkID0gNCksCiAgICAgIGxlZ2VuZCA9IGxpc3QoeCA9IDAuNSwgeGFuY2hvciA9ICJjZW50ZXIiLCB5ID0gMC4yLCBiZ2NvbG9yID0gInJnYmEoMCwwLDAsMCkiLCB0aXRsZT0iTWV0cmljIiwgb3JpZW50YXRpb24gPSAiaCIpLAogICAgICBhdXRvc2l6ZSA9IEYKICAgICkKICAKICBwbHRfQWxsQWNjW1twXV0gPC0gcGxvdF9BY2MKfQoKCmh0bWx0b29sczo6dGFnTGlzdChwbHRfQWxsQWNjKQpgYGAKCgpgYGB7cn0KbGlicmFyeShkZW5kZXh0ZW5kKQoKTlVNQkVSX09GX0NMVVNURVJTID0gNAoKY29sb3JfZGFya3BpbmsgPSAiI2U3NTQ4MCIKQ0xVU1RFUl9CUkFOQ0hfQ09MT1JTIDwtIGMoImJsdWUiLCAiZGFya3JlZCIsIGNvbG9yX2RhcmtwaW5rLCAiYmxhY2siKVsxOk5VTUJFUl9PRl9DTFVTVEVSU10KQ0xVU1RFUl9MQUJFTF9DT0xPUlMgPC0gYygiYmx1ZSIsICJkYXJrcmVkIiwgY29sb3JfZGFya3BpbmssICJibGFjayIpWzE6TlVNQkVSX09GX0NMVVNURVJTXQoKCmRmUFAgPC0gYXMuZGF0YS5mcmFtZShjYmluZCgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVubGlzdChtZWFuX3BwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmxpc3Qoc3RkX3BwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmxpc3QobWVhbl9wcF9zZWcwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmxpc3QobWVhbl9wcF9zZWcxKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmxpc3QobWVhbl9wcF9zZWcyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmxpc3QobWVhbl9wcF9zZWczKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmxpc3QobWVhbl9wcF9zZWc0KSkpCgpuYW1lcyhkZlBQKSA8LSBjKCJNZWFuUFAiLCAiU3RkUFAiLCAiTWVhblBQX1NlZzAiLCAiTWVhblBQX1NlZzEiLCAiTWVhblBQX1NlZzIiLCAiTWVhblBQX1NlZzMiLCAiTWVhblBQX1NlZzQiKQpiZWhhdmlvcmFsTWF0cml4Q2x1c3RlcmluZyA8LSBhcy5tYXRyaXgoZGZQUCkKCmRpc3RNYXRyaXggPC0gZGlzdChiZWhhdmlvcmFsTWF0cml4Q2x1c3RlcmluZykKaHJlc3VsdHMgPC0gZGlzdE1hdHJpeCAlPiUgaGNsdXN0CgpoYyA8LSBocmVzdWx0cyAlPiUgCiAgICAgIGFzLmRlbmRyb2dyYW0gJT4lCiAgICAgIHNldCgibm9kZXNfY2V4IiwgTlVNQkVSX09GX0NMVVNURVJTKSAlPiUKICAgICAgc2V0KCJsYWJlbHNfY29sIiwgdmFsdWUgPSBDTFVTVEVSX0xBQkVMX0NPTE9SUywgaz1OVU1CRVJfT0ZfQ0xVU1RFUlMpICU+JQogICAgICAjIHNldCgibGVhdmVzX3BjaCIsIDE5KSAlPiUKICAgICAgIyBzZXQoImxlYXZlc19jb2wiLCB2YWx1ZSA9IGMoImdyYXkiKSwgaz1OVU1CRVJfT0ZfQ0xVU1RFUlMpICU+JSAgICAKICAgICAgc2V0KCJicmFuY2hlc19rX2NvbG9yIiwgdmFsdWU9Q0xVU1RFUl9CUkFOQ0hfQ09MT1JTLCBrPU5VTUJFUl9PRl9DTFVTVEVSUykKCnBsb3QoaGMpCmxlZ2VuZCgidG9wcmlnaHQiLCAKICAgICB0aXRsZT0iRHJpdmU9Q29nbml0aXZlIFxuSGllcmFjaGljYWwgQ2x1c3RlcmluZyIsCiAgICAgbGVnZW5kID0gYygiRXhjZXB0aW9uYWwgSW5jcmVhc2Ugb2YgUFAiICwgIlNsaWdodGx5IEluY3JlYXNlIG9mIFBQIiAsICJOby1jaGFuZ2Ugb3IgRGVjcmVhc2Ugb2YgUFAiKSwgCiAgICAgY29sID0gYygiZGFya3JlZCIsICJwaW5rIiAsICJibHVlIiksCiAgICAgcGNoID0gYygyMCwyMCwyMCksIGJ0eSA9ICJuIiwgIHB0LmNleCA9IDEuNSwgY2V4ID0gMC44ICwgCiAgICAgdGV4dC5jb2wgPSAiYmxhY2siLCBob3JpeiA9IEZBTFNFLCBpbnNldCA9IGMoMC40LCAwLjEpKQpgYGAKCgoKYGBge3J9CiMgU3RvcmUgY2x1c3RlcmluZyBkYXRhCmZQYXRoIDwtIHN0cl9pbnRlcnAoIi4uLy4uLy4uL2RhdGEvVFQxL3ByZXByb2Nlc3NlZC9BbmFseXNpcy9UVDFfRHJpdmVfMV9QUC5jc3YiKQpkZnggPC0gZGZQUApkZnggPC0gY2JpbmQocGVyc29ucywgZGZ4KQpuYW1lcyhkZngpIDwtIGMoIlN1YmplY3QiLCBuYW1lcyhkZlBQKSkKd3JpdGUuY3N2KGRmeCwgZlBhdGgsIHJvdy5uYW1lcyA9IEYpCmBgYAoKCgo=